//
// A log writer that is controlled, and outputs to Event Tracing for Windows.

#ifndef LONGKEY_BASE_ETW_LOG_WRITER_H_
#define LONGKEY_BASE_ETW_LOG_WRITER_H_

#include "event_trace_provider.h"
#include "logging.h"

class EtwLogWriter : public LogWriter, public EtwTraceProvider
{
public:
	static const GUID kLKAgentTraceGuid;

	// The event ID for the event types below.
	static const GUID kLogEventId;

	// The event type for a simple UTF-8 zero-terminated message event.
	static const EtwEventType kLogMessageType = 10;

	// The event type for a log message with a stack trace, followed by the
	// zero-terminated UTF-8 message text.
	static const EtwEventType kLogMessageWithStackTraceType = 11;

	// The lowest-order enable flags bit turn on stack trace capture.
	// The remaining enable bits correspond to log categories, starting
	// from LC_LOGGING through LC_MAX_CAT - 1.
	static const EtwEventFlags kCaptureStackTraceMask = 0x0001;

	// LogWriter overrides
	virtual bool WantsToLogRegardless() const;
	virtual bool IsCatLevelEnabled(LogCategory category, LogLevel level) const;
	virtual void OutputMessage(const OutputInfo* output_info);

	// Factory for new instance;
	static EtwLogWriter* Create();

	// Convert a log category to the corresponding ETW enable flag.
	static EtwEventFlags CategoryToEnableFlag(LogCategory category);

	// Convert from a log level to the corresponding ETW trance level
	static EtwEventLevel LogLevelToTraceLevel(LogLevel level);

protected:
	explicit EtwLogWriter(const GUID& provider_guid);
	virtual void Cleanup();

	// Override from EtwTraceProvider.
	virtual void OnEventsEnabled();
	virtual void OnEventsDisabled();

private:
	// The CaptureStackBackTrace function is only available as of Windows XP,
	// and is only declared in SDK headers as of the Vista SDK. To uncomplicated
	// things we get at the function through GetProcAddress.
	typedef WORD (NTAPI* RtlCaptureStackBackTraceFunc)(DWORD frames_to_skip,
		DWORD frames_to_capture, PVOID* backtrace, PDWORD backtrace_hash);

	RtlCaptureStackBackTraceFunc rtl_capture_stack_backtrace_;

	DISALLOW_EVIL_CONSTRUCTORS(EtwLogWriter);
};

#endif	// LONGKEY_BASE_ETW_LOG_WRITER_H_